//
//  SDataUtil.swift
//  niuguwang
//
//  Created by BrightLi on 2021/2/9.
//  Copyright © 2021年 taojinzhe. All rights reserved.
//

import Foundation
import UIKit
import CommonCrypto

extension Array
{
    subscript (safe index: Int) -> Element? {
        if(isEmpty){
            return nil
        }
        return (0..<count).contains(index) ? self[index] : nil
    }
}

@objcMembers open class SDataUtil:NSObject
{
    public static var blackList:Array<String>=["0x3.me"];
    public static var desKey:String = "abcde123fghij456abcde123456"
    
    // 读取本地文件
    dynamic public class func loadFile(_ fileName:String,type:String)->String{
        if fileName.isEmpty{
            return ""
        }
        let path = Bundle.main.path(forResource: fileName, ofType: type);
        let url = URL(fileURLWithPath: path!)
        do{
            let data = try Data(contentsOf: url)
            if let result=String(data: data, encoding: .utf8){
                return result
            }
            return ""
        }catch{
            return "";
        }
    }
    
    dynamic public class func hasPrefix(_ source:String,target:String)->Bool
    {
        return source.hasPrefix(target)
    }
    
    dynamic public class func urlQuery(_ value:[String:Any])->String
    {
        let result=value.map{"\($0)=\($1)"}.joined(separator: "&")
        return result
    }
    
    // 范围取值
    dynamic public class func clamp(_ value:Int,min:Int,max:Int) -> Int
    {
        if value < min{
            return value
        }
        if value >= max{
            return max
        }
        return value
    }
    // 返回整形
    dynamic public class func uint32Of(_ value:Any!) -> UInt32
    {
        return uint32Of(value, valid:0)
    }
    // 返回整形
    dynamic public class func uint32Of(_ value:Any!,valid:UInt32) -> UInt32
    {
        guard let _:Any = value else{
            return valid
        }
        let temp = NSString(format:"%@",(value as! CVarArg))
        if temp.length > 0 {
            return UInt32(temp.intValue)
        }
        return valid
    }
    // 返回整形
    dynamic public class func intOf(_ value:Any?) -> Int
    {
        return intOf(value, valid:0)
    }
    // 返回整形
    dynamic public class func intOf(_ value:Any?,valid:Int=0) -> Int
    {
        if value == nil{
            return valid
        }
        if value! is Int{
            return value! as! Int
        }
        if let arg=value as? CVarArg{
            let temp = NSString(format:"%@",arg)
            if temp.length > 0 {
                return Int(temp.intValue)
            }
        }
        return valid
    }
    // 返回整形
    dynamic public class func intOf(_ dict:[String:Any]?,keys:[String]?,valid:Int=0) -> Int
    {
        if dict == nil || keys == nil || keys!.count<1{
            return valid
        }
        for key in keys!
        {
            if dict!.keys.contains(key){
                return intOf(dict![key])
            }
        }
        return valid
    }
    // Int转NSNumber
    dynamic public class func numberOfInt(_ value:Any?,valid:Int=0)->NSNumber
    {
        let result=NSNumber(value:SDataUtil.intOf(value,valid:valid))
        return result
    }
    // 返回无符号整形
    dynamic public class func uintOf(_ value:Any?,valid:UInt=0)->UInt
    {
        guard let _:Any = value else{
            return valid
        }
        if value is UInt{
            return value as! UInt
        }
        let temp = NSString(format:"%@",(value as! CVarArg))
        if temp.length > 0 {
            return UInt(temp.intValue)
        }
        return valid
    }
    // 返回整形
    dynamic public class func intOfArray(_ target:Any!,index:Int,valid:Int) -> Int
    {
        guard let _:Any = target else{
            return valid
        }
        guard let list:Array<Any> = target as? Array<Any> else{
            return valid
        }
        if let item:Any = list[safe:index]{
            return intOf(item, valid: valid)
        }
        return valid
    }
    dynamic public class func intOfDict(_ target:[String:Any]?,path:[String],valid:Int=0) ->Int
    {
        if target == nil{
            return valid
        }
        var temp:Int=valid
        var dict:[String:Any]?
        for (index,key) in path.enumerated(){
            if index<path.count-1{
                dict = (dict==nil ?target![key]:dict![key]) as? [String:Any]
                if dict == nil{
                    return valid
                }
            }else{
                temp = SDataUtil.intOf(dict == nil ?target![key]:dict![key],valid: valid)
            }
        }
        return temp
    }
    // 返回布尔值
    dynamic public class func boolOf(_ value:Any?) -> Bool
    {
        let target:Int = intOf(value)
        if target != 0{
            return true
        }
        return false
    }
    // 返回布尔值
    dynamic public class func boolOf(_ value:Any!,key:String!) -> Bool
    {
        let target:String = stringOf(value)
        if target == key{
            return true
        }
        return false
    }
    // 返回布尔值
    dynamic public class func boolOf(_ value:Any!,keys:[String]) -> Bool
    {
        let target:String = stringOf(value)
        for key in keys
        {
            if target == key{
                return true
            }
        }
        return false
    }
    // 返回浮点数
    dynamic public class func floatOf(_ value:Any?) -> Float
    {
        return floatOf(value, valid: 0)
    }
    // 返回浮点数
    dynamic public class func floatOf(_ value:Any?,valid:Float) -> Float
    {
        if value == nil{
            return valid
        }
        if let number:NSNumber = value as? NSNumber{
            return number.floatValue
        }
        var string:String = SDataUtil.stringOf(value)
        if string.hasSuffix("%"){
            string.remove(at: string.index(before:string.endIndex))
        }
        if let temp = Float(string){
            return temp
        }
        return valid
    }
    
    // 返回浮点数
    dynamic public class func doubleOf(_ value:Any?) -> Double
    {
        return doubleOf(value, valid: 0)
    }
    
    // 返回浮点数
    dynamic public class func doubleOf(_ value:Any?,valid:Double) -> Double
    {
        if value == nil{
            return valid
        }
        if let number:NSNumber = value as? NSNumber{
            return number.doubleValue
        }
        var string:String = SDataUtil.stringOf(value)
        if string.hasSuffix("%"){
            string.remove(at: string.index(before:string.endIndex))
        }
        if let temp = Double(string){
            return temp
        }
        return valid
    }
    
    dynamic public class func stringOfDouble(_ value:Any!) ->NSString
    {
        let number = doubleOf(value)
        let decimal = 4
        let fmt = NSString(format: "%%.%df",decimal)
        var temp = NSString(format: fmt,number);
        let len:Int = temp.length
        for _ in 0..<len
        {
            if !temp.hasSuffix("0"){
                break;
            }else{
                temp = temp.substring(to: temp.length-1) as NSString
            }
        }
        if temp.hasPrefix(".")//避免像1.000这样的被解析成1.
        {
            return temp.substring(to: temp.length-1) as NSString
        }
        return temp
    }
    // 返回字符串
    dynamic public class func stringOf(_ value:Any?) -> String
    {
        return stringOf(value,valid:"")
    }
    // 返回字符串
    dynamic public class func stringOf(_ value:Any?,valid:String) -> String
    {
        guard let _:Any = value else{
            return valid
        }
        if let temp = value as? String{
            return temp.count>0 ?temp:valid
        }
        if let temp = value as? Substring{
            return String(temp)
        }
        let temp = String(format:"%@",value as! CVarArg)
        if temp == "<null>"{
            return valid
        }
        if temp.count > 0 {
            return temp
        }
        return valid
    }

    dynamic public class func decodeURL(_ value:String)->String{
        return value.removingPercentEncoding ?? value
    }
    
    dynamic public class func stringOfDict(_ target:[String:Any]?,path:[String],valid:String="") ->String
    {
        if target == nil{
            return valid
        }
        var temp:String=valid
        var dict:[String:Any]?
        for (index,key) in path.enumerated(){
            if index<path.count-1{
                dict = (dict==nil ?target![key]:dict![key]) as? [String:Any]
                if dict == nil{
                    return valid
                }
            }else{
                temp = SDataUtil.stringOf(dict == nil ?target![key]:dict![key],valid:valid)
            }
        }
        return temp
    }
    // 返回Data
    dynamic public class func dataOf(_ target:Any?)->Data?{
        if let temp = target as? Data{
            return temp
        }
        if let temp = target as? String{
            return temp.data(using: .utf8)
        }
        return nil
    }
    
    // 从数组中返回字符串
    dynamic public class func stringOfArray(_ target:Any!,index:Int) -> String
    {
        return stringOfArray(target,index: index,valid: "")
    }
    // 从数组中返回字符串
    dynamic public class func stringOfArray(_ target:Any!,index:Int,valid:String) -> String
    {
        guard let _:Any = target else{
            return valid
        }
        guard let list:Array<Any> = target as? Array<Any> else{
            return valid
        }
        if let item:Any = list[safe:index]{
            return stringOf(item, valid: valid)
        }
        return valid
    }
    // 从字典中返回字符串
    dynamic public class func stringOfDict(_ dict:[String:Any]?,keys:[String],valid:String="") -> String
    {
        if dict == nil{
            return valid
        }
        for key in keys
        {
            if dict!.keys.contains(key){
                return stringOf(dict![key],valid:valid)
            }
        }
        return valid
    }
    // 获得数组
    dynamic public class func arrayOf(_ target:Any?) -> [Any]?
    {
        guard let _:Any = target else{
            return nil
        }
        guard let list=target as? [Any] else{
            return nil
        }
        return list
    }
    // 获得字典数组
    dynamic public class func dictArrayOf(_ target:Any?) -> [[String:Any]]?
    {
        guard let _:Any = target else{
            return nil
        }
        guard let list=target as? [[String:Any]] else{
            return nil
        }
        return list
    }
    // 获得数组
    dynamic public class func arrayOf(_ target:[String:Any],keys:[String]) ->[Any]?
    {
        var temp:[Any]?
        for key:String in keys{
            temp = SDataUtil.arrayOf(target[key])
            if temp != nil{
                return temp
            }
        }
        return temp
    }
    dynamic public class func arrayOfDict(_ target:[String:Any]?,path:[String]) ->[Any]?
    {
        if target == nil{
            return nil
        }
        var temp:[Any]?
        var dict:[String:Any]?
        for (index,key) in path.enumerated(){
            if index<path.count-1{
                dict = (dict==nil ?target![key]:dict![key]) as? [String:Any]
                if dict == nil{
                    return nil
                }
            }else{
                temp = (dict == nil ?target![key]:dict![key]) as? [Any]
            }
        }
        return temp
    }
    dynamic public class func dictArrayOfDict(_ target:[String:Any]?,path:[String]) ->[[String:Any]]?
    {
        if target == nil{
            return nil
        }
        var temp:[[String:Any]]?
        var dict:[String:Any]?
        for (index,key) in path.enumerated(){
            if index<path.count-1{
                dict = (dict==nil ?target![key]:dict![key]) as? [String:Any]
                if dict == nil{
                    return nil
                }
            }else{
                temp = (dict == nil ?target![key]:dict![key]) as? [[String:Any]]
            }
        }
        return temp
    }
    // 从数组中获得可变数组
    dynamic public class func arrayOfArray(_ target:Any?,index:Int) -> [Any]?
    {
        guard let _:Any = target else{
            return nil
        }
        guard let list:Array<Any> = target as? Array<Any> else{
            return nil
        }
        return arrayOf(list[safe:index])
    }
    // 获得可变数组
    dynamic public class func mutableArrayOf(_ target:Any!) -> NSMutableArray?
    {
        guard let _:Any = target else{
            return nil
        }
        if let item:NSMutableArray = target as? NSMutableArray{
            return item
        }
        if let array:[Any] = target as? [Any]{
            return NSMutableArray(array: array)
        }
        return nil
    }
    // 从数组中获得可变数组
    dynamic public class func mutableArrayOfArray(_ target:Any?,index:Int) -> NSMutableArray?
    {
        guard let _:Any = target else{
            return nil
        }
        guard let list:Array<Any> = target as? Array<Any> else{
            return nil
        }
        return mutableArrayOf(list[safe:index])
    }
    // 获得字典
    dynamic public class func dictOf(_ target: Any!) -> [String: Any]?
    {
        guard let _:Any = target else{
            return nil
        }
        if let dict:[String: Any] = target as? [String: Any]{
            return dict
        }
        return nil
    }
    dynamic public class func dictOfDict(_ target:[String:Any],path:[String]) ->[String:Any]?
    {
        var temp:[String:Any]?
        var dict:[String:Any]?
        for (index,key) in path.enumerated(){
            if index<path.count-1{
                dict = (dict==nil ?target[key]:dict![key]) as? [String:Any]
                if dict == nil{
                    return nil
                }
            }else{
                temp = (dict == nil ?target[key]:dict![key]) as? [String:Any]
            }
        }
        return temp
    }
    // 获得字典
    dynamic public class func dictOfString(_ target:String) -> [String:String]
    {
        let list = target.split(separator: ",")
        var result = Dictionary<String,String>()
        for item in list{
            let obj = item.split(separator: "=")
            if obj.count>1{
                let key = SDataUtil.stringOfArray(obj,index:0)
                let value = SDataUtil.stringOfArray(obj,index:1)
                if key.count>0{
                    result[key as String] = value as String
                }
            }
        }
        return result
    }
    dynamic public class func paramsOfURL(_ path:String)->[String:String]?
    {
        guard let url=URL(string:path) else{
            return nil
        }
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else{
            return nil
        }
        guard let queryItems = components.queryItems else{
            return nil
        }
        let result = queryItems.reduce(into: [String: String]()) { (result, item) in
            result[trim(item.name)] = item.value
        }
        return result
    }
    // 获得可变字典
    dynamic public class func mutableDictOf(_ target: Any!) -> NSMutableDictionary?
    {
        guard let _:Any = target else{
            return nil
        }
        if let item:NSMutableDictionary = target as? NSMutableDictionary{
            return item
        }
        if let dict:[AnyHashable: Any] = target as? [AnyHashable: Any]{
            return NSMutableDictionary(dictionary: dict)
        }
        return nil
    }
    // 从数组中获得字典
    dynamic public class func dictOfArray(_ target: Any?,index:Int) -> [String:Any]?
    {
        guard let list:[Any] = target as? [Any] else{
            return nil
        }
        return dictOf(list[safe:index])
    }
    // 从数组中获得可变字典
    dynamic public class func mutableDictOfArray(_ target: Any,index:Int) -> NSMutableDictionary?
    {
        guard let list:Array<Any> = target as? Array<Any> else{
            return nil
        }
        return mutableDictOf(list[safe:index])
    }
    // 从数组中获得可变字典
    dynamic public class func dataOfArray(_ target: Any?,index:Int) -> Any?
    {
        guard let list:Array<Any> = target as? Array<Any> else{
            return nil
        }
        return list[safe:index]
    }
    dynamic public class func isNull(_ value:Any?)->Bool{
        if value == nil{
            return true
        }
        if value is NSNull{
            return true
        }
        return false
    }
    
    //是否为纯数字
    dynamic public class func isPurnFloat(string: String) -> Bool {
        let scan: Scanner = Scanner(string: string)
        var val:Float = 0
        return scan.scanFloat(&val) && scan.isAtEnd
    }
    

    // base64编码
    dynamic public class func base64Encode(_ value: String) -> String {
        let data: Data? = value.data(using: .utf8)
        return data?.base64EncodedString(options: []) ?? ""
    }
    // base64 解码
    dynamic public class func base64Decode(_ value: String) -> String {
        let data = Data(base64Encoded: value, options: [])
        return String(data: data ?? Data(), encoding: .utf8) ?? ""
    }
    
    dynamic public class func digit(_ value:String,valid:Int)->Int{
        if value.count<1{
            return 0
        }
        if value == "--"{
            return 0
        }
        var string:String = SDataUtil.stringOf(value)
        if string.hasSuffix("%"){
            string.remove(at: value.index(before:string.endIndex))
        }
        if let range = string.range(of: ".", options: .backwards){
            let startIndex = string.index(range.lowerBound,offsetBy:1)
            string = String(string[startIndex..<string.endIndex])
            if string.count<1{
                return valid
            }
            return string.count
        }
        return valid
    }
    // 将转换成JSON
    dynamic public class func jsonOfDict(_ dict:[String:Any]) -> String
    {
        if(!JSONSerialization.isValidJSONObject(dict)){
            return ""
        }
        if #available(iOS 11.0, *) {
            if let data = try?JSONSerialization.data(withJSONObject: dict, options: .sortedKeys){
                if let json:String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String?{
                    return json
                }
            }
            return ""
        } else {
            if let data = try?JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted){
                if let json:String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String?{
                    return json
                }
            }
            return ""
        }
    }
    
    // 将转换成JSON
    dynamic public class func jsonOfDictArray(_ value:[[String:Any]]) -> String
    {
        if(!JSONSerialization.isValidJSONObject(value)){
            return ""
        }
        if #available(iOS 11.0, *) {
            if let data = try?JSONSerialization.data(withJSONObject: value, options: .sortedKeys){
                if let json:String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String?{
                    return json
                }
            }
            return ""
        } else {
            if let data = try?JSONSerialization.data(withJSONObject: value, options: .prettyPrinted){
                if let json:String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String?{
                    return json
                }
            }
            return ""
        }
    }
    
    dynamic public class func error(_ code:Int,msg:String)->Error!
    {
        let desc = NSLocalizedString(msg, comment: "")
        let userInfo = [NSLocalizedDescriptionKey: desc]
        let error = NSError(domain: "", code: 1000, userInfo: userInfo)
        return error
    }
    
    dynamic public class func dictArrayOfJson(_ source:String)->[[String:Any]]?
    {
        guard let data=source.data(using: .utf8) else{
            return nil
        }
        guard let result = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String:Any]] else{
            return nil
        }
        return result
    }
    
    
    dynamic public class func getDictionaryFromJSONString(jsonString:String) ->NSDictionary{
        
        let jsonData:Data = jsonString.data(using: .utf8)!
     
        let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if dict != nil {
            return dict as! NSDictionary
        }
        return NSDictionary()
         
     
    }
    
    
    dynamic public class func jsonOfData(_ data:Data?) -> Any!
    {
        guard let data = data else{
            return error(9000,msg:"解析JSON错误:数据错误")
        }
        if data.count<1{
            return error(9001,msg:"解析JSON错误:数据为空值")
        }
        var source = String(data:data,encoding:.utf8) ?? ""
        if source.hasPrefix("<!DOCTYPE"){
            return error(9002,msg:"解析JSON错误:返回的是HTML")
        }
        var result = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
        if result != nil{
            return result
        }
        source = source.replacingOccurrences(of: "\r\n", with: "")
        source = source.replacingOccurrences(of: "\n", with: "")
        source = source.replacingOccurrences(of: "\t", with: "")
        source = source.replacingOccurrences(of: "\\", with: "")
        let jsonData = source.data(using: .utf8)!
        result = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if result != nil{
            return result
        }
        return error(9003,msg:String(format:"解析JSON错误:%@",source))
    }
    // 比较版本号
    dynamic public class func compareVersion(_ current:String,target:String)->Bool
    {
        let currentList = current.components(separatedBy: ".")
        let targetList = target.components(separatedBy: ".")
        for index in 0 ... currentList.count{
            let s = SDataUtil.intOfArray(currentList,index:index,valid:0)
            let t = SDataUtil.intOfArray(targetList,index:index,valid:0)
            if s > t {
                return false
            }
        }
        return true
    }
    
    // 获得URL参数值
    dynamic public class func urlParam(_ url:String,key:String) -> String
    {
        if url.count<1 {
            return ""
        }
        if (url.contains("?")){
            if (url.contains("&")){
                let params=url.components(separatedBy: "&")
                for value in params{
                    let pair = value.components(separatedBy: "=")
                    let k = pair.first?.removingPercentEncoding
                    let v = pair.last?.removingPercentEncoding
                    if k == key{
                        return v ?? ""
                    }
                }
            }else{
                let params = url.components(separatedBy: "?")
                let pair = params.last?.components(separatedBy: "=")
                let k = pair?.first?.removingPercentEncoding
                let v = pair?.last?.removingPercentEncoding
                if k == key{
                    return v ?? ""
                }
            }
        }
        return ""
    }
    // h5是否无效
    dynamic public class func invalidH5(_ value: String) -> Bool {
        if value.count<1{
            return true
        }
        for key:String in blackList{
            if value.contains(key){
                return true
            }
        }
        return false
    }
    // 比较 NSDictionary
    dynamic public class func isEqualToDictionary(_ source:[String:Any],target:[String:Any])->Bool
    {
        return NSDictionary(dictionary:source).isEqual(to: target)
    }
    // 比较数组
    dynamic public class func isEqual(_ source:[String],target:[String])->Bool
    {
        if source.count != target.count{
            return false
        }
        for (index,a) in source.enumerated(){
            let b = target[index]
            if a != b{
                return false
            }
        }
        return true
    }
    
    // 删除前后多余的空格
    dynamic public class func trim(_ target:String?) -> String
    {
        guard let temp = target else{
            return ""
        }
        if temp.isEmpty{
            return ""
        }
        let result = temp.trimmingCharacters(in: .whitespacesAndNewlines)
        return result
    }
    
    dynamic public class func isMobile(_ mobile:String) -> Bool
    {
        if (mobile.count != 11)
        {
            return false;
        }
        let phone = "1[0-9]{10}"
        let reg = NSPredicate(format: "SELF MATCHES %@",phone)
        return reg.evaluate(with: mobile)
    }
    
    dynamic public class func encode3DES(_ source:String,key:String) -> String
    {
        guard let keyData = key.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) as NSData? else{
            return source
        }
        guard let data  = source.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) as NSData? else{
            return source
        }
        let keyBytes = UnsafeRawPointer(keyData.bytes)
        let dataLength = size_t(data.length)
        let dataBytes = UnsafeRawPointer(data.bytes)
        let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
        let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes)
        let cryptLength  = size_t(cryptData!.length)
        let iv:NSString = "12312300"
        let viData :NSData = iv.data(using: String.Encoding.utf8.rawValue)! as NSData
        let viDataBytes    = UnsafeRawPointer(viData.bytes)
        
        let ccop = CCOperation(kCCEncrypt)
        // 特定的几个参数
        let keyLength              = size_t(kCCKeySize3DES)
        let operation: CCOperation = UInt32(ccop)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)
        let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding)
        
        var numBytesCrypted :size_t = 0
        
        let cryptStatus = CCCrypt(operation, // 加密还是解密
            algoritm, // 算法类型
            options,  // 密码块的设置选项
            keyBytes, // 秘钥的字节
            keyLength, // 秘钥的长度
            viDataBytes, // 可选初始化向量的字节
            dataBytes, // 加解密内容的字节
            dataLength, // 加解密内容的长度
            cryptPointer, // output data buffer
            cryptLength,  // output data length available
            &numBytesCrypted) // real output data length
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData!.length = Int(numBytesCrypted)
            if let data = cryptData as Data?{
                let result=data.bytes.toHexString()
                return result
            }
        } else {
            print("Error: \(cryptStatus)")
        }
        return source
    }
    
    dynamic public class func decode3DES(_ source:String,key:String) -> String
    {
        guard let keyData:NSData = key.data(using: .utf8) as NSData? else{
            return ""
        }
        guard let data  = hexToData(source) else {
            return ""
        }
        let keyBytes = UnsafeRawPointer(keyData.bytes)
        
        let dataLength = size_t(data.length)
        let dataBytes = UnsafeRawPointer(data.bytes)
        let cryptData    = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)
        let cryptPointer = UnsafeMutableRawPointer(cryptData!.mutableBytes)
        let cryptLength  = size_t(cryptData!.length)
        let iv:NSString = "12312300"
        let viData :NSData = iv.data(using: String.Encoding.utf8.rawValue)! as NSData
        let viDataBytes    = UnsafeRawPointer(viData.bytes)
        
        let ccop = CCOperation(kCCDecrypt)
        // 特定的几个参数
        let keyLength              = size_t(kCCKeySize3DES)
        let operation: CCOperation = UInt32(ccop)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)
        let options:   CCOptions   = UInt32(kCCOptionPKCS7Padding)
        
        var numBytesCrypted :size_t = 0
        
        let cryptStatus = CCCrypt(operation, // 加密还是解密
            algoritm, // 算法类型
            options,  // 密码块的设置选项
            keyBytes, // 秘钥的字节
            keyLength, // 秘钥的长度
            viDataBytes, // 可选初始化向量的字节
            dataBytes, // 加解密内容的字节
            dataLength, // 加解密内容的长度
            cryptPointer, // output data buffer
            cryptLength,  // output data length available
            &numBytesCrypted) // real output data length
        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData!.length = Int(numBytesCrypted)
            if let result = String(data: cryptData! as Data, encoding: .utf8){
                return result
            }
            return ""
        } else {
            print("Error: \(cryptStatus)")
        }
        return ""
    }
    
    dynamic public class func md5(_ value:String)->String
    {
        let str = value.cString(using: .utf8)
        let strLen = CUnsignedInt(value.lengthOfBytes(using:.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)
        let hash = NSMutableString()
        for i in 0 ..< digestLen {
            hash.appendFormat("%02x", result[i])
        }
        result.deinitialize(count: digestLen)
        return String(format: hash as String)
    }
    
    dynamic public class func hexToData(_ source:String) -> NSData!
    {
        let data = NSMutableData()
        var idx: Int = 0
        idx = 0
        let temp = source as NSString
        while idx + 2 <= temp.length {
            let range = NSRange(location: idx, length: 2)
            let hexStr = temp.substring(with: range)
            let scanner = Scanner(string: hexStr)
            var intValue:UInt32 = 0
            scanner.scanHexInt32(&intValue)
            data.append(&intValue,length:1)
            idx += 2
        }
        return data
    }
    
    dynamic public class func cookie(_ domain:String,key:String) -> String
    {
        let storage = HTTPCookieStorage.shared
        for cookie:HTTPCookie in storage.cookies ?? [] {
            if (cookie.domain == domain) {
                if (cookie.name == key) {
                    return cookie.value
                }
            }
        }
        return ""
    }
    
    dynamic public class func clearCookie(_ domain:String,key:String)
    {
        let storage = HTTPCookieStorage.shared
        for cookie:HTTPCookie in storage.cookies ?? [] {
            if (cookie.domain == domain) {
                if !(cookie.name == key) {
                    storage.deleteCookie(cookie)
                }
            }
        }
    }
    
    dynamic public class func clearCookie()
    {
        let storage = HTTPCookieStorage.shared
        for cookie:HTTPCookie in storage.cookies ?? [] {
            storage.deleteCookie(cookie)
        }
    }
    
    dynamic public class func removePlus(_ target:NSString) -> NSString
    {
        if target.length<1{
            return ""
        }
        if target.hasPrefix("+"){
            return target.substring(from:1) as NSString
        }
        if target.hasPrefix("-"){
            return target.substring(from:1) as NSString
        }
        return target
    }
    
    dynamic public class func encodeURLQuery(_ target:String?) ->String{
        if target == nil || target!.count<1{
            return ""
        }
        let result = target!.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
        return result ?? target!
    }
    
    dynamic public class func encodeURL(_ target:String?) -> String
    {
        if target==nil || target!.count<1{
            return ""
        }
        let charSet = CharacterSet(charactersIn: "|{}\"/?&=;+!@#$()',* >").inverted
        let result = target!.addingPercentEncoding(withAllowedCharacters: charSet)
        return result ?? target!
    }
    
    dynamic public class func encode(_ target:String,characters:String) -> String
    {
        if target.count<1 {
            return ""
        }
        let charSet = CharacterSet(charactersIn:characters).inverted
        let result = target.addingPercentEncoding(withAllowedCharacters: charSet)
        return result ?? target
    }
    
    dynamic public class func colorToHex(_ target:UIColor) -> NSString
    {
        if let components = target.cgColor.components{
            let red = Int(components.count>0 ? components[0] * 255.0:0)
            let green =  Int( components.count>1 ? components[1] * 255.0:0)
            let blue = Int( components.count>2 ? components[2] * 255.0:0)
            let hex = NSString(format: "#%02x%02x%02x", red, green, blue)
            return hex
        }
        return "unkown"
    }
    
    dynamic public class func urlParam(_ url:String,key:String,value:String)->String
    {
        var charSet = CharacterSet.urlQueryAllowed
        charSet.insert("#")
        charSet.insert("%")
        guard let temp=url.addingPercentEncoding(withAllowedCharacters: charSet) else{
            return url
        }
        guard let components = NSURLComponents.init(string: temp) else{
            return url
        }
        if var items=components.queryItems{
            for (index,item) in items.enumerated()
            {
                if item.name == key{
                    items[index].value = value
                    components.queryItems = items
                    let result=components.url?.absoluteString ?? url;
                    return result
                }
            }
            items.append(URLQueryItem(name: key, value: value))
            components.queryItems = items
            let result=components.url?.absoluteString ?? url;
            return result
        }
        components.query=String(format:"%@=%@",key,value)
        let result=components.url?.absoluteString ?? url;
        return result
    }
    
    dynamic public class func isEmptyString(_ value:String?)->Bool{
        if value == nil{
            return true
        }
        if value!.count<1{
            return true
        }
        if value == "(null)"{
            return true
        }
        return false
    }
    
    dynamic public class func isEmptyDict(_ value:[String:Any]?)->Bool{
        if value == nil{
            return true
        }
        if value!.isEmpty{
            return true
        }
        return false
    }
    // 可考虑用泛型来优化
    dynamic public class func limit(_ value:[Any],max:Int)->[Any]{
        if value.count<=max{
            return value
        }
        let total=min(value.count,max)
        var temp = [Any]()
        for i in 0..<total{
            temp.append(value[i])
        }
        return temp
    }
    
    dynamic public class func isImgURL(_ url:String?)->Bool{
        if url == nil || url!.count<1{
            return false
        }
        if !url!.hasPrefix("http"){
            SLog.debug("# 无效的图片地址:%@",url!)
            return false
        }
        if !url!.hasPrefix("https:"){
            SLog.debug("# 警告:不支持https %@",url!)
        }
        return true;
    }
    // 随机数
    dynamic public class func random(_ min:Int,max:Int)->Int{
        let value=Int.random(in:min..<max+1)
        return value
    }
    // 洗牌
    dynamic public class func shuffle(_ target:[Any])->[Any]{
        var temp=target
        temp.sort { (a, b) -> Bool in
            let random=Int.random(in:0..<2)
            return (random==1)
        }
        return temp
    }
    
    // 带正号的百分比
    dynamic public class func percentPlus(_ value:Double)->String{
        let percent:Double=(value*100).rounded()/100
        if value>0{
            return String(format:"+%.2f%%",percent)
        }else{
            return String(format:"%.2f%%",percent)
        }
    }
    // 得到中英文混合字符串长度
    dynamic public class func doubleCount(_ value:String?)->Int
    {
        if value == nil || value!.count<1{
            return 0
        }
        let encode = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue)))
        if let data = value!.data(using: encode){
            return data.count
        }
        return 0
    }
}
